package myansible

import (
	"ginplay/myproxy"
	"ginplay/mytool"

	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"os/exec"

	"github.com/gin-gonic/gin"
)

type GETPAGEREQUEST struct {
	Pagenow  int    `json:"pagenow"`
	Pagesize int    `json:"pagesize"`
	Search   string `json:"search"`
}

type ANSIBLES struct {
	Id      int    `json:"id"`
	Name    string `json:"name"`
	Hosts   string `json:"hosts"`
	Pattern string `json:"pattern"`
	Module  string `json:"module"`
	Args    string `json:"args"`
	Forks   string `json:"forks"`
	Key     string `json:"key"`
	Proxy   string `json:"proxy"`
}

func getContent(onegetrequest GETPAGEREQUEST) []ANSIBLES {
	tsql := "select id,name,hosts,pattern,module,args,forks,key,proxy from myansible where name like ? limit ?,?"
	rows := mytool.SelectByPara(tsql, "%"+onegetrequest.Search+"%", (onegetrequest.Pagenow-1)*onegetrequest.Pagesize, onegetrequest.Pagesize)
	defer rows.Close()
	var myplaybook []ANSIBLES
	for rows.Next() {
		var oneplay ANSIBLES
		rows.Scan(&oneplay.Id, &oneplay.Name, &oneplay.Hosts, &oneplay.Pattern, &oneplay.Module,
			&oneplay.Args, &oneplay.Forks, &oneplay.Key, &oneplay.Proxy)
		myplaybook = append(myplaybook, oneplay)
	}
	return myplaybook
}

func getAllCount(onegetrequest GETPAGEREQUEST) string {
	tsql := "select count(1) as allcount from myansible where name like ?"
	rows := mytool.SelectByPara(tsql, "%"+onegetrequest.Search+"%")
	defer rows.Close()
	var allcount string
	for rows.Next() {
		rows.Scan(&allcount)
	}
	return allcount
}

type RETURNRESULT struct {
	Result   []ANSIBLES `json:"result"`
	Allcount string     `json:"allcount"`
}

func GetByPage(c *gin.Context) {
	var onegetrequest GETPAGEREQUEST
	if err := c.BindJSON(&onegetrequest); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	fmt.Println(onegetrequest)
	myplaybook := getContent(onegetrequest)
	allcount := getAllCount(onegetrequest)
	var returnresult RETURNRESULT
	returnresult.Allcount = allcount
	returnresult.Result = myplaybook
	jsonData, _ := json.Marshal(returnresult)
	fmt.Println(string(jsonData))
	c.String(http.StatusOK, string(jsonData))
}

func Realadd(c *gin.Context) {
	var oneplay ANSIBLES
	if err := c.BindJSON(&oneplay); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	tsql := `insert into myansible (name,hosts,pattern,module,args,forks,key,proxy) VALUES
	( ?,?,?,?,?,?,?,? )`
	mytool.UpdateByPara(tsql, oneplay.Name, oneplay.Hosts, oneplay.Pattern, oneplay.Module, oneplay.Args, oneplay.Forks, oneplay.Key, oneplay.Proxy)
	c.String(http.StatusOK, string("添加成功"))
}

func GetContentByID(id string) ANSIBLES {
	tsql := "select id,name,hosts,pattern,module,args,forks,key,proxy from myansible where id = ?"
	rows := mytool.SelectByPara(tsql, id)
	defer rows.Close()
	var oneplay ANSIBLES
	for rows.Next() {
		rows.Scan(&oneplay.Id, &oneplay.Name, &oneplay.Hosts, &oneplay.Pattern, &oneplay.Module, &oneplay.Args,
			&oneplay.Forks, &oneplay.Key, &oneplay.Proxy)
	}
	return oneplay
}

func GetById(c *gin.Context) {
	id := c.Query("id")
	oneplay := GetContentByID(id)
	jsonData, _ := json.Marshal(oneplay)
	c.String(http.StatusOK, string(jsonData))
}

func Update(c *gin.Context) {
	var oneplay ANSIBLES
	c.BindJSON(&oneplay)
	tsql := "replace into myansible (id,name,hosts,pattern,module,args,forks,key,proxy) VALUES(?,?,?,?,?,?,?,?,?)"
	mytool.UpdateByPara(tsql, oneplay.Id, oneplay.Name, oneplay.Hosts, oneplay.Pattern, oneplay.Module, oneplay.Args, oneplay.Forks, oneplay.Key, oneplay.Proxy)
	c.String(http.StatusOK, string("更新成功"))
}

func DeleteById(c *gin.Context) {
	id := c.Query("id")
	tsql := "delete from myansible where id = ?"
	mytool.UpdateByPara(tsql, id)
	c.String(http.StatusOK, string("删除成功"))
}

func CopyById(c *gin.Context) {
	id := c.Query("id")
	tsql := "insert into myansible (name,hosts,pattern,module,args,forks,key,proxy) select ?,hosts,pattern,module,args,forks,key,proxy from myansible where id = ?"
	mytool.UpdateByPara(tsql, "bycopyfrom-id"+id, id)
	c.String(http.StatusOK, string("复制成功"))
}

func writeStrTofile(filepath string, writecontent string) {
	file, _ := os.Create(filepath)
	defer file.Close()
	file.Write([]byte(writecontent))
}

func runcommandBack(oneplay ANSIBLES) string {
	inifile := fmt.Sprintf("/tmp/ansible%d.ini", oneplay.Id)
	logfile := fmt.Sprintf("/tmp/ansible%d.log", oneplay.Id)
	writeStrTofile(inifile, oneplay.Hosts)
	var command string
	if oneplay.Proxy == "false" {
		command = fmt.Sprintf(`ansible --private-key %s -i %s %s -m %s -a '%s' -f %s 2>&1 | tee %s`, oneplay.Key, inifile,
			oneplay.Pattern, oneplay.Module, oneplay.Args, oneplay.Forks, logfile)
	} else {
		proxyinfo := myproxy.GetByName(oneplay.Proxy)
		command = fmt.Sprintf(`ansible --ssh-common-args='-o ProxyCommand="ssh -i %s -W %%h:%%p -p 22 -q %s@%s"' --private-key %s -i %s %s -m %s -a '%s' -f %s 2>&1 | tee %s`,
			proxyinfo.Key, proxyinfo.User, proxyinfo.Address, oneplay.Key, inifile, oneplay.Pattern, oneplay.Module, oneplay.Args, oneplay.Forks, logfile)
	}
	fmt.Println(command)
	myresult := exec.Command("sh", "-c", command)
	out, err := myresult.Output()
	if err != nil {
		fmt.Println(err)
	}
	file, _ := os.OpenFile(logfile, os.O_APPEND|os.O_WRONLY, 0644)
	defer file.Close()
	file.WriteString("ENDENDEND")
	return string(out)
}

func RunById(c *gin.Context) {
	id := c.Query("id")
	oneplay := GetContentByID(id)
	go runcommandBack(oneplay)
	c.String(http.StatusOK, fmt.Sprintf("%d", oneplay.Id))
}

func Getlog(c *gin.Context) {
	id := c.Query("id")
	content, _ := os.ReadFile(fmt.Sprintf("/tmp/ansible%s.log", id))
	c.String(http.StatusOK, string(content))
}

func CheckTable() {
	tsql := `select name from sqlite_master where name="myansible"`
	rows := mytool.SelectNoPara(tsql)
	defer rows.Close()
	if rows.Next() {
		fmt.Println("myansible is exits")
	} else {
		fmt.Println("create myansible")
		csql := `
CREATE TABLE myansible (
  id INTEGER PRIMARY KEY,
  name varchar(200) DEFAULT '',
  hosts text DEFAULT '',
  pattern varchar(200) DEFAULT '',
  module varchar(100) DEFAULT '',
  args text DEFAULT '',
  forks varchar(50) DEFAULT '',
  key varchar(50) DEFAULT '',
  proxy varchar(50) default 'false'
);
        `
		mytool.UpdateNoPara(csql)
	}
}
